package algos;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.PathIterator;

public class Isovist {
   public Shape Perimeter;
   public Area perimArea;
   public Point P;
   private final int NUM_RAYES = 360;
   public Point[] rays = new Point[NUM_RAYES*2];
   public Polygon polygon = new Polygon();
   
   public Isovist(Area perim){
	   perimArea = (Area) perim.clone();
	   Perimeter = (Shape) perim.clone();
   }
   public void returnToDefault(){
	   Perimeter = (Shape) perimArea.clone();
   }
   public void createHoles(Shape[] holes){
	   Area temp = (Area) perimArea.clone();
	   for (int i = 0; i < holes.length; i++) {
		Area a = new Area(holes[i]);
		temp.subtract(a);
	   }
	   Perimeter = temp;
   }
	public Isovist(Shape perim, Point pt){
		Perimeter = perim;
		P = pt;
		doIso(P);
	}
	
	public void doIso(Point pt){
		P = pt;
		double xt,yt,mx,my;
		double x1,x2,x3,x4,y1,y2,y3,y4;
		double[] coords = {0.,0.,0.,0.,0.,0.};
		PathIterator pit = Perimeter.getPathIterator(null);
		int j = 0;
		for( int i=0; i<NUM_RAYES; i++ ){
			xt =  (P.x + 1000.0d*Math.sin(Math.toRadians((double)i)));
			yt =  (P.y + 1000.0d*Math.cos(Math.toRadians((double)i)));
			
			x1 = P.getX();
			y1 = P.getY();
			
			double u12,u34,t;
			pit = Perimeter.getPathIterator(null);
			
            x3 = 0.;
            x4 = 0.;
            y3 = 0.;
            y4 = 0.;
            mx = 0.;
            my = 0.;
            boolean ok=false;
            
            while( !pit.isDone() ) {
				x2 = xt;
				y2 = yt;

                if( pit.currentSegment(coords)==PathIterator.SEG_MOVETO ){
                	mx = coords[0];
                	my = coords[1];
					x3 = mx;
					y3 = my;
					ok=false;
				}else if( pit.currentSegment(coords)==PathIterator.SEG_LINETO ){
					x4 = coords[0];
					y4 = coords[1];
					ok=true;
				}else if( pit.currentSegment(coords)==PathIterator.SEG_CLOSE){
					x4 = mx;
					y4 = my;
					ok=true;
				}
                
 // * segment intersection calculation adapted from http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
                if( ok ){
                t = ((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
				if( t != 0.0d ){
					u12 = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))/t;
					u34 = ((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))/t;
					if( (u34>0.0d && u34<1.0d)&&(u12>0.0d&&u12<1.0d) ){  //intersects boundary segment
						xt = x1+u12*(x2-x1);
						yt = y1+u12*(y2-y1);
						//System.out.println(" ray "+i+" ("+xt+","+yt+")"+u34);
					}
				}
				x3=x4;
				y3=y4;
                }
				pit.next();
				} 
						
			rays[j] = new Point((int) xt, (int) yt);
			j++;
			//System.out.println(" ray "+i+" ("+xt+","+yt+")");
			}
		int [] xpoints = new int[rays.length]; 
		int [] ypoints = new int[rays.length];
		
		for (int i = 0; i < NUM_RAYES; i++) {
			xpoints[i] = rays[i].x;
			ypoints[i] = rays[i].y;
//			System.out.println(i);
		}
		polygon.xpoints = xpoints;
		polygon.ypoints = ypoints;
		polygon.npoints = NUM_RAYES;
	}
	public void paint( Graphics2D g2d ){
		g2d.setColor(Color.red);
		g2d.draw( Perimeter );
		int [] xpoints = new int[rays.length]; 
		int [] ypoints = new int[rays.length];
		
		for (int i = 0; i < NUM_RAYES; i++) {
			xpoints[i] = rays[i].x;
			ypoints[i] = rays[i].y;
		}
		polygon.xpoints = xpoints;
		polygon.ypoints = ypoints;
		polygon.npoints = NUM_RAYES;
		g2d.setColor(Color.yellow);
		g2d.fill(polygon);
		g2d.drawPolygon(polygon);
	}
}
	


